package com.ym.core.es.config;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSONObject;
import com.ym.core.es.domain.bo.HeightWordTags;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义resultmap,支持高亮转换
 *
 * @author: 李涛
 * @version: 2020年09月01日 11:17
 */

@Slf4j
@Component
public class HighlightResultMapper implements SearchResultMapper {


	@Override
	public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
		long totalHits = response.getHits().getTotalHits();
		List<T> list = new ArrayList<>();
		// 获取搜索结果
		SearchHits hits = response.getHits();
		for (SearchHit searchHit : hits) {
			if (hits.getHits().length <= 0) {
				continue;
			}
			// 获取高亮字段Map
			Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
			// 将json字符串转化为对象
			T item = JSONObject.parseObject(searchHit.getSourceAsString(), clazz);
			if (Objects.isNull(item)) {
				continue;
			}
			// 变量替换值
			highlightFields.forEach((fieldName, highlightFieldsValue) -> {
				StringBuilder sb = new StringBuilder();
				Text[] fragments = highlightFieldsValue.getFragments();
				for (Text text : fragments) {
					sb.append(text);
				}
				// 替换重复标签
				String finalSb = sb.toString();
				HeightWordTags[] heightWordTags = HeightWordTags.values();
				for (HeightWordTags heightWordTag : heightWordTags) {
					finalSb = finalSb.replace(heightWordTag.getRepeatTag(), "");
				}
				ReflectUtil.setFieldValue(item, fieldName, finalSb);
			});
			list.add(item);
		}
		return new AggregatedPageImpl<>(list, pageable, totalHits);
	}
}
